#pragma once

#include <string>
#include <vector>

#include "cv_common.hpp"
#include "cv_object.hpp"
#include "opencv2/opencv.hpp"

class Detection {
 public:
  cv::Rect2i face_;
  std::vector<cv::Rect2i> eyes_;
  std::vector<cv::Rect2i> noses_;
  Detection(cv::Rect2i face, std::vector<cv::Rect2i> eyes,
            std::vector<cv::Rect2i> noses);
};

class CVFaceDetector {
 private:
  std::vector<Face> faces_;
  std::vector<cv::Rect2i> eyes_;
  // std::vector<Detection> detections_;
  cv::CascadeClassifier face_cascader_, eye_cascader_, nose_cascader_;

  uint8_t model_;

  std::size_t DetectFace(const cv::Mat& frame, std::vector<cv::Rect2i>& rects);
  std::size_t DetectNose(const cv::Mat& frame, std::vector<cv::Rect2i>& rects);
  std::size_t DetectEyes(const cv::Mat& frame, std::vector<cv::Rect2i>& rects);

 public:
  CVFaceDetector();
  CVFaceDetector(const std::string& face_param, const std::string& eye_param,
                 const std::string& nose_param,
                 uint8_t model = component::DetectModel::kMODEL_FACE);
  ~CVFaceDetector();

  Expr LoadParams(const std::string& face_param, const std::string& eye_param,
                  const std::string& nose_param);

  void ConfigModel(uint8_t model);

  Expr Detect(const cv::Mat& frame, double scale = 1.);

  void VisualizeResult(const cv::Mat& output, bool add_lable);
};
